package pers.ree.demo.base;

/**
 * 四种实现方案
 * 1. 使用数组 用临时变量交换元素
 * 2. 使用数组 用异或运算（只能用于整数）
 * 3. 使用数组 用加减运算
 * 4. 使用成员变量
 *
 * 二种错误方案
 * 1. 直接交换
 * 2. 使用包装类交换
 */
public class SwapNumberDemo {

    /****** 1. 使用数组 用临时变量交换元素 begin ***/
    public static void swapWithArrayAndTemp(int[] arr) {
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1] = temp;
    }

    public static void exeSwapWithArrayAndTemp() {
        int[] arr = {10, 20};

        System.out.println("exeSwapWithArrayAndTemp，交换前，" + "arr[0]=" + arr[0] + "，arr[1]=" + arr[1]);

        swapWithArrayAndTemp(arr);

        System.out.println("exeSwapWithArrayAndTemp，交换后，" + "arr[0]=" + arr[0] + "，arr[1]=" + arr[1]);
    }
    /****** 使用数组 用临时变量交换元素 end ***/


    /****** 2. 使用数组 用异或运算（只能用于整数） begin ***/
    /**
     * 只能用于整数(short, int, long)，double，float无法使用^运算，编译会报错
     * 原理：
     * a ^ a = 0, a ^ 0 = a
     *  =》
     * a ^ b = c,
     *     c ^ b = a ^ (b ^ b) = a ^ 0 = a;
     *     c ^ a = (a ^ a) ^ b = b ^ 0 = b;
     */
    public static void swapWithArrayAndXOR(int[] arr) {
        arr[0] ^= arr[1];
        arr[1] ^= arr[0];
        arr[0] ^= arr[1];
    }

    public static void exeSwapWithArrayAndXOR() {
        int[] arr = {100, 200};

        System.out.println("exeSwapWithArrayAndXOR，交换前，" + "arr[0]=" + arr[0] + "，arr[1]=" + arr[1]);

        swapWithArrayAndXOR(arr);

        System.out.println("exeSwapWithArrayAndXOR，交换后，" + "arr[0]=" + arr[0] + "，arr[1]=" + arr[1]);
    }
    /****** 使用数组 用异或运算（只能用于整数） end ***/


    /****** 3. 使用数组 用加减运算 begin ***/
    /**
     * 原理：加减法的结合律和交换律
     * a + b - b = a，a + b -a = b
     */
    public static void swapWithArrayAndAddSub(int[] arr) {
        arr[0] += arr[1];
        arr[1] = arr[0] - arr[1];
        arr[0] = arr[0] - arr[1];
    }

    public static void exeSwapWithArrayAndAddSub() {
        int[] arr = {1000, 2000};

        System.out.println("swapWithArrayAndAddSub，交换前，" + "arr[0]=" + arr[0] + "，arr[1]=" + arr[1]);

        swapWithArrayAndAddSub(arr);

        System.out.println("swapWithArrayAndAddSub，交换后，" + "arr[0]=" + arr[0] + "，arr[1]=" + arr[1]);
    }
    /****** 使用数组 用加减运算 end ***/


    /****** 4. 使用成员变量 交换数值 begin ***/
    class SwapNumber {
        private int a, b;

        public int getA() {
            return a;
        }

        public void setA(int a) {
            this.a = a;
        }

        public int getB() {
            return b;
        }

        public void setB(int b) {
            this.b = b;
        }

        public void swapWithMemberVar(int a, int b) {
            this.a = b;
            this.b = a;
        }
    }

    public static void exeSwapWithMemberVar() {
        SwapNumber swapNumber = new SwapNumberDemo().new SwapNumber();
        swapNumber.setA(11);
        swapNumber.setB(21);

        System.out.println("exeSwapWithMemberVar，交换前，" + "swapNumber.a=" + swapNumber.getA() + "，swapNumber.b=" + swapNumber.getB());

        swapNumber.swapWithMemberVar(swapNumber.getA(), swapNumber.getB());

        System.out.println("exeSwapWithMemberVar，交换后，" + "swapNumber.a=" + swapNumber.getA() + "，swapNumber.b=" + swapNumber.getB());
    }
    /****** 使用成员变量 交换数值 end ***/


    /****** 错误1 直接交换 begin ***/
    /**
     * Java的方法参数是值传递，所以无法直接交换
     */
    public static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }

    public static void exeSwap() {
        int a = 12, b = 22;

        System.out.println("exeSwap，交换前，" + "a=" + a + "，b=" + b);

        swap(a, b);

        System.out.println("exeSwap，交换后，" + "a=" + a + "，b=" + b);
    }
    /****** 错误1 直接交换 end ***/


    /****** 错误2 使用包装类交换 begin ***/
    /**
     * 为什么使用包装类无法实现交换，因为包装类的value是final的，初始化后无法修改，
     * Java的参数又是值传递，所以直接交换包装类也不行
     */
    public static void swapWithPackagingClass(Integer a, Integer b) {
        Integer temp = a;
        a = b;
        b = temp;
    }

    public static void exeSwapWithPackagingClass() {
        Integer a = new Integer(13), b = new Integer(23);

        System.out.println("exeSwapWithPackagingClass，交换前，" + "a=" + a + "，b=" + b);

        swapWithPackagingClass(a, b);

        System.out.println("exeSwapWithPackagingClass，交换后，" + "a=" + a + "，b=" + b);
    }
    /****** 错误2 使用包装类交换 end ***/


    public static void main(String[] args) {
        // 正确的四种实现
        exeSwapWithArrayAndTemp();
        exeSwapWithArrayAndXOR();
        exeSwapWithArrayAndAddSub();
        exeSwapWithMemberVar();

        // 错误的两种实现
        exeSwap();
        exeSwapWithPackagingClass();
    }
}
